package com.javasm.service;

import com.alibaba.fastjson.JSONObject;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * 自定义 UsernamePasswordAuthenticationFilter，从请求中获取用户名密码
 */
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    //更改用户信息
    public static void setLoginUser(UserDetails userDetails) {
        SecurityContextHolder.getContext().setAuthentication(
                new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities()));
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        //如果请求方式不是 post，直接异常
        if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("请求方式有误：" + request.getMethod());
        }
        //如果请求的参数格式不是json，直接异常
        if (!request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){
            throw new AuthenticationServiceException("参数不是json：" + request.getMethod());
        }
        String username=null;
        String password = null;
        String code =null;
        try {
            //从 json 数据中 获取用户名、密码
            Map<String,String> map = JSONObject.parseObject(request.getInputStream(),Map.class);
            code=map.get("code");
            username = map.get("username");//但是参数名可能不是这个，最好是用 getUsernameParameter() 方法获取参数名
            password = map.get("password");
        } catch (IOException e) {
            throw new AuthenticationServiceException("参数不对：" + request.getMethod());
        }
        //先校验验证码
        String verify_code = (String) request.getSession().getAttribute("verify_code");
        if (code == null || verify_code == null || !code.equals(verify_code)) {
            throw new AuthenticationServiceException("验证码错误");
        }
        //再校验用户名及密码
        if (username == null) {
            username = "";
        }
        if (password == null) {
            password = "";
        }
        username = username.trim();
        // 封装用户名、密码，下面的 authenticate 方法会从中拿到 用户名， 调用我们的 LoginUserService 获取用户，然后比较密码
        UsernamePasswordAuthenticationToken authRequest
                = new UsernamePasswordAuthenticationToken(username,password);
        //设置ip、sessionId信息
        setDetails(request,authRequest);
        // authenticate 方法中封装了具体的密码认证逻辑
//        //认证管理器(AuthenticationManager)进行认证
        return this.getAuthenticationManager().authenticate(authRequest);
    }
}